package com.yyaccp.hncc.oss.aliyun.controller;

import com.ruoyi.common.core.domain.AjaxResult;
import com.yyaccp.hncc.common.vo.oss.OssCallbackResult;
import com.yyaccp.hncc.common.vo.oss.OssPolicyResult;
import com.yyaccp.hncc.common.vo.oss.UploadResult;
import com.yyaccp.hncc.oss.aliyun.service.OssService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author 天天向上 （john.yi@qq.com）
 * @date 2020/8/19
 */
@RestController
@RequestMapping("/aliyun/oss")
@RequiredArgsConstructor
@Slf4j
public class OssController {
    private final OssService ossService;

    @GetMapping("/policy")
    public AjaxResult policy() {
        OssPolicyResult ossPolicyResult = ossService.ossPolicy();
        if(log.isDebugEnabled()) {
            log.debug("签名结果：" + ossPolicyResult);
        }
        return  AjaxResult.success("操作成功", ossPolicyResult);
    }

    /**
     * 阿里云oss自动回调的控制器
     * @param request
     * @param response
     * @throws IOException
     */
    @PostMapping("/callback")
    public void callback(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /**
         * 应用服务器根据OSS发送消息中的authorization来进行验证，
         * 如果验证通过，则向OSS返回如下Json格式的成功消息
         * String value: OK
         * Key: Status
         */
        OssCallbackResult ossCallbackResult = ossService.ossCallback(request.getParameterMap());
        if(log.isDebugEnabled()) {
            log.debug("回调结果：" + ossCallbackResult);
        }
        // 按要求响应给OSS
        response.getWriter().println( "{\"Status\":\"OK\"}");
        response.setStatus(HttpServletResponse.SC_OK);
        response.flushBuffer();
    }
    /**
     * 普通方式上传文件到阿里云oss
     * 可以通过下载获取该文件
     * 此方式需要前端上传到应用服务器，再由应用服务器上传到oss，浪费应用服务器流量和资源
     * 后续可以按oss最佳实践中的服务端签名直传并设置回调来实现，网址如下
     * https://help.aliyun.com/document_detail/31927.html?spm=a2c4g.11186623.6.1568.29ac6e28Jv2KyO
     * @param desc 文件描述
     * @param files 上传的文件数组
     * @return 上传结果map，失败为empty map
     */
    @PostMapping("/upload")
    public Object upload(String desc, @RequestParam("files") MultipartFile[] files){
        Assert.notNull(files, "请选择上传的文件");
        final Map<String, Object> result = new HashMap<>(10);
        Arrays.stream(files).forEach(multipartFile -> {
            String originalFilename = multipartFile.getOriginalFilename();
            try (InputStream in = multipartFile.getInputStream()){
                UploadResult uploadResult = ossService.upload(originalFilename, in);
                result.put(uploadResult.getFilename(), uploadResult);
            } catch (IOException e) {
                log.error("上传文件-{}-失败", originalFilename,  e);
            }
        });
        return result;
    }
    /**
     * 根据文件名从oss下载文件到本地
     * @param filename 存储在oss上的唯一的文件名
     * @param response 无
     */
    @GetMapping("/download")
    public void download(String filename, HttpServletResponse response) {
        Assert.notNull(filename,"文件名不能为空");
        // 通用文件下载响应头设置
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
        try (OutputStream out = response.getOutputStream()) {
            String result = ossService.download(filename, out);
            log.info("下载文件{}成功，{}", filename, result);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

}
